package com.tegtech.tools.aws.support;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;

import com.tegtech.common.utils.date.DatePattern;
import com.tegtech.common.utils.date.DateUtils;
import com.tegtech.tools.aws.properties.AwsProperties;

import cn.hutool.core.util.IdUtil;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;

/**
 * 亚马逊S3文件预签名、上传处理类
 * @Author Jun
 * @date 2021年2月22日 下午12:28:08
 */
public class S3FilePresigner {

	private static S3Presigner s3Presigner;
	
	static {
		if(s3Presigner == null) {
			s3Presigner = S3Presigner.builder()
					.region(AwsProperties.s3Region)
					.credentialsProvider(StaticCredentialsProvider.create(AwsProperties.awsBasicCredentials))
					.build();
		}
	}

	/**
	 * 生成文件预签名URL
	 * 
	 * @param keyName
	 * @return
	 */
	public static String generatePresignedUrl(String keyName, String contentType) {

		// PutObjectRequest
		PutObjectRequest putObjectRequest = PutObjectRequest.builder()
				.bucket(AwsProperties.getS3Bucket())
				.key(keyName)
				.contentType(contentType)
				.contentLength(AwsProperties.getS3MaxContentLength())
				.build();

		// PutObjectPresignRequest
		PutObjectPresignRequest putObjectPresignRequest = PutObjectPresignRequest.builder()
				.signatureDuration(Duration.ofMinutes(AwsProperties.getS3MaxPresignUrlDuration()))
				.putObjectRequest(putObjectRequest)
				.build();

		// PresignedPutObjectRequest
		PresignedPutObjectRequest presignedPutObjectRequest = s3Presigner.presignPutObject(putObjectPresignRequest);

		URL presignedUrl = presignedPutObjectRequest.url();

		System.out.println("Presigned URL: " + presignedUrl);
		System.out.println("Method needed: " + presignedPutObjectRequest.httpRequest().method());

		return presignedUrl.toString();
	}

	/**
	 * 获取文件预览URL
	 * @param keyName
	 * @return
	 */
	public static String getPresignedUrl(String keyName) {

		// Create a GetObjectRequest to be pre-signed
		GetObjectRequest getObjectRequest = GetObjectRequest.builder()
				.bucket(AwsProperties.getS3Bucket())
				.key(keyName)
				.build();
		
		// Create a GetObjectPresignRequest to specify the signature duration
		GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder()
				.signatureDuration(Duration.ofMinutes(AwsProperties.getS3MaxPresignUrlDuration()))
				.getObjectRequest(getObjectRequest)
				.build();
		
		// Generate the presigned request
		PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(getObjectPresignRequest);
		
		return presignedGetObjectRequest.url().toString();
	}

	/**
	 * 将本地文件上传到指定的presignedUrl
	 * @param presignedUrl
	 * @param objectLocalPath
	 * @param contentType
	 */
	public static void uploadObjectByPresignedUrl(String presignedUrl, String objectLocalPath, String contentType) {
		BufferedOutputStream bufferedOutputStream = null;
		BufferedInputStream bufferedInputStream = null;
		try {
			HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(presignedUrl).openConnection();
			httpURLConnection.setDoOutput(true);
			httpURLConnection.setRequestProperty("Content-Type", contentType);
			httpURLConnection.setRequestMethod("PUT");

			bufferedOutputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());
			// Read from local and write to S3.
			bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(objectLocalPath)));
			byte[] buffer = new byte[1024];
			int length = bufferedInputStream.read(buffer);
			while (length > 0) {
				// Write.
				bufferedOutputStream.write(buffer);
				// Read next.
				length = bufferedInputStream.read(buffer);
			}
			bufferedOutputStream.flush();
			bufferedOutputStream.close();
			System.out.println("Response Code: " + httpURLConnection.getResponseCode());
			System.out.println("Response Message: " + httpURLConnection.getResponseMessage());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bufferedOutputStream != null) {
				try {
					bufferedOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bufferedInputStream != null) {
				try {
					bufferedInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 获取文件KeyName
	 * @param folder	上传文件夹名称
	 * @param format	文件格式
	 * @return
	 */
	public static String getFileKeyName(String folder, String format) {
		return new StringBuffer(folder)
				.append("/")
				.append(DateUtils.formatCurrentDate(DatePattern.YYYYMMDD))
				.append("/")
				.append(IdUtil.fastSimpleUUID())
				.append(format)
				.toString();
	}
	
}
